#FunancePresict.py
def parseCSV(filename):    #parseCSV()读取csv文件，并将里面的内容表示为列表类型
    dataName,data = [],[]    #定义列表dataName存储每一行的行名称，列表data存储每一行的财政数据
    f = open(filename,'r',encoding='utf-8')    #仅获取数据，不作修改，故用'r'
    for line in f:    #对于文件的每一行
        splitedLine = line.strip('\n').split(',')    #除去换行符和逗号，将剩下的数据存为字符串列表splitedLine
        if'指标'in splitedLine[0]:    #对‘指标’那一行
            years = [int(x[:-1]) for x in splitedLine[1:]]    #[]切去字符串列表splitedLine每个元素x的‘年’字，将剩下的每个字符串元素x转化为整数列表years的整数元素
        else:    #对不是‘指标’标那一行
            dataName.append('{:10}'.format(splitedLine[0]))    #获取行第一个元素作为行名称。此处采用了append，可以在保留上一行的数据的前提下继续补充
            data.append([float(x) for x in splitedLine[1:]])    #获取行的其他元素作为财政数据
    f.close()    #每一行都操作完之后，关闭文件，释放文件操作权
    return years,dataName,data    #返回各个年份组成的整数列表years，各行名称组成的字符串列表dataName，财政数据组成的浮点列表data

def means(data):    #means()求平均函数
    return sum(data)/len(data)    #data中数值的总和除以data的长度（即data中数据的数量n）


def linearRegression(xlist,ylist):    #linearRegression()求线性回归参数a、b
    xmeans,ymeans = means(xlist),means(ylist)    #分别求x平均和y平均
    bNumerator = -len(xlist)*xmeans*ymeans    #求-nx平均y平均
    bDenominator = -len(xlist)*xmeans**2    #求-n（x）^2
    for x,y in zip(xlist,ylist):    #对于xlist和ylist组成的每一个数对(即公式中的（xi,yi）)
        bNumerator += x*y    #分子bNumerator等于-nx平均y平均加上xi*yi
        bDenominator += x**2    #分母bDenominator等于-n（x）^2加上(xi)^2
    b = bNumerator/bDenominator    #分子bNumerator除以分母bDenominator得到参数b
    a = ymeans-b*xmeans    #由a的性质得到a
    return a,b    #返回a、b的值

def calNewData(newyears,a,b):   #calNewData()求线性回归估计
    return[(a+b*x) for x in newyears]   #将新的年份x代入线性回归公式a+b*x中求新的财政数据y

def showResults(years,dataNames,newDatas):      #showResults()格式化输出处理结果
    print('{:^60}'.format('国家财政收支线性估计'))    #输出表头‘国家财政收支线性估计’
    header = '指标'    #heder作为标题行
    for year in years:
        header += '{:10}'.format(year)  #每个年份数字后补上10个字宽，并连接成一整个字符串
    print(header)    #首先打印标题行header
    for name,lineData in zip(dataNames,newDatas):   #取出行名称列表dataNames的每一个元素name，取出新财政数据newDatas的每一个子列表lineData
        line = name    #单个行名称name赋值给line
        for data in lineData:   #子列表lineData中再取出各个数据data
            line += '{:>10.1f}'.format(data)    #line与data中的每一个值连接
        print(line)    #输出line

def main():    #定义主方法main()来综合所有方法
    newyears = [x+2010 for x in range(7)]    #用列表newyears存储包括2010~2017的年份数据
    newDatas = []    #声明一个列表newDatas来表示加入估计数据后的新数据
    years,dataNames,datas = parseCSV('finance.csv')    #用parseCSV来为原年份years、原行名称dataNames、原财政数据datas赋值
    for data in datas:
        a,b = linearRegression(years,data)    #用linearRegression()方法计算线性回归参数
        newDatas.append(calNewData(newyears,a,b))    #列表newDatas来表示加入估计数据后的新数据
    showResults(newyears,dataNames,newDatas)     #格式化输出新年份、行名称、新数据的结果）

main()    #运行main()方法
